package com.lg.dao;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;

import com.ibatis.sqlmap.client.SqlMapClient;

@SuppressWarnings("unchecked")
public class EntityDAOImpl<T extends Serializable> implements EntityDAO<T> {
	private SqlMapClient sqlMapClient;
	private String className;

	public EntityDAOImpl() {
	}

	public EntityDAOImpl(Class<T> clazz) {
		this.className = (clazz.getSimpleName() + ".").toUpperCase();
	}

	public EntityDAOImpl(String clazz) {
		className = (clazz.substring(clazz.lastIndexOf(".") + 1) + ".")
				.toUpperCase();
	}

	public SqlMapClient getSqlMapClient() {
		return sqlMapClient;
	}

	public void setSqlMapClient(SqlMapClient sqlMapClient) {
		this.sqlMapClient = sqlMapClient;
	}

	public <C extends Criteria> int countByExample(Example<C> example)
			throws SQLException {
		try {
			return (Integer) sqlMapClient.queryForObject(className
					+ EntityDAO.COUNTBYEXAMPLE, example);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	public int countByStatementId(String statementId, Object param)
			throws SQLException {
		try {
			return (Integer) sqlMapClient.queryForObject(className
					+ statementId, param);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	public <C extends Criteria> int deleteByExample(Example<C> example)
			throws SQLException {
		try {
			return sqlMapClient.delete(className + EntityDAO.DELETEBYEXAMPLE,
					example);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	public int deleteByPrimaryKey(T id) throws SQLException {
		try {
			return sqlMapClient.delete(
					className + EntityDAO.DELETEBYPRIMARYKEY, id);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	public Object insert(T record) throws SQLException {
		try {
			return (T) sqlMapClient
					.insert(className + EntityDAO.INSERT, record);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	public void insertBatch(Collection<T> conllection) throws SQLException {
		try {
			sqlMapClient.startBatch();
			int batch = 0;
			for (T record : conllection) {
				sqlMapClient.insert(className + EntityDAO.INSERTSELECTIVE,
						record);
				batch++;
				if (batch == 200) {
					sqlMapClient.executeBatch();
					batch = 0;
				}
			}
			sqlMapClient.executeBatch();
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	public Object insertSelective(T record) throws SQLException {
		try {
			return (T) sqlMapClient.insert(className
					+ EntityDAO.INSERTSELECTIVE, record);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	public T selectByPrimaryKey(T id) throws SQLException {
		try {
			return (T) sqlMapClient.queryForObject(className
					+ EntityDAO.SELECTBYPRIMARYKEY, id);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	public <C extends Criteria> List<T> selectListByExample(Example<C> example)
			throws SQLException {
		try {
			return sqlMapClient.queryForList(className
					+ EntityDAO.SELECTBYEXAMPLE, example);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	public <C extends Criteria> List<T> selectListByExample(Example<C> example,
			int start, int count) throws SQLException {
		try {
			return sqlMapClient.queryForList(className
					+ EntityDAO.SELECTBYEXAMPLE, example, start, count);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	public List<T> selectListByStatementId(String statementId, Object param)
			throws SQLException {
		try {
			return sqlMapClient.queryForList(className + statementId, param);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	public List<T> selectListByStatementId(String statementId, Object param,
			int start, int count) throws SQLException {
		try {
			return sqlMapClient.queryForList(className + statementId, param,
					start, count);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	public <C extends Criteria> T selectObjectByExample(Example<C> example)
			throws SQLException {
		try {
			return (T) sqlMapClient.queryForObject(className
					+ EntityDAO.SELECTBYEXAMPLE, example);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	public T selectObjectByStatementId(String statementId, Object param)
			throws SQLException {
		try {
			return (T) sqlMapClient.queryForObject(className + statementId,
					param);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	public <C extends Criteria> int updateByExample(T record, Example<C> example)
			throws SQLException {
		UpdateByExampleParms parms = new UpdateByExampleParms(record, example);
		try {
			return sqlMapClient.update(className + EntityDAO.UPDATEBYEXAMPLE,
					parms);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	public <C extends Criteria> int updateByExampleSelective(T record,
			Example<C> example) throws SQLException {
		UpdateByExampleParms parms = new UpdateByExampleParms(record, example);
		try {
			return sqlMapClient.update(className
					+ EntityDAO.UPDATEBYEXAMPLESELECTIVE, parms);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	public int updateByPrimaryKey(T record) throws SQLException {
		try {
			return sqlMapClient.update(
					className + EntityDAO.UPDATEBYPRIMARYKEY, record);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	public int updateByPrimaryKeySelective(T record) throws SQLException {
		try {
			return sqlMapClient.update(className
					+ EntityDAO.UPDATEBYPRIMARYKEYSELECTIVE, record);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	private static class UpdateByExampleParms extends Example<Criteria> {
		private Object record;

		public <C extends Criteria> UpdateByExampleParms(Object record,
				Example<C> example) {
			super(example);
			this.record = record;
		}

		public Object getRecord() {
			return record;
		}
	}

	public int deleteByStatementId(String statementId, Object param)
			throws SQLException {
		try {
			return sqlMapClient.delete(className + statementId, param);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	public Object insertByStatementId(String statementId, Object param)
			throws SQLException {
		try {
			return sqlMapClient.insert(className +statementId, param);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	public int updateyStatementId(String statementId, Object param)
			throws SQLException {
		try {
			return sqlMapClient.update(className +statementId, param);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

	public List<String> selectListNameByStatementId(String statementId,
			Object param) throws SQLException {
		try {
			return sqlMapClient.queryForList(className +statementId, param);
		} catch (Exception e) {
			throw new SQLException(e.getMessage());
		}
	}

}